#include "bsp_sound.h"

#define SOUND_PORT I2C_NUM_0
#define I2C_SCL_PIN 1
#define I2C_SDA_PIN 0

#define I2S_MCK_PIN 3
#define I2S_BCK_PIN 2
#define I2S_DATA_WS_PIN 5
#define I2S_DATA_OUT_PIN 6
#define I2S_DATA_IN_PIN 4

#define PA_GPIO 7

static i2c_master_bus_handle_t i2c_bus_handle;
static i2s_chan_handle_t       speakerHandle;
static i2s_chan_handle_t       micHandle;

static esp_codec_dev_handle_t codec_dev;

void bsp_sound_i2c_init(void)
{
    i2c_master_bus_config_t i2c_bus_config      = {0};
    i2c_bus_config.clk_source                   = I2C_CLK_SRC_DEFAULT;
    i2c_bus_config.i2c_port                     = SOUND_PORT;
    i2c_bus_config.scl_io_num                   = I2C_SCL_PIN;
    i2c_bus_config.sda_io_num                   = I2C_SDA_PIN;
    i2c_bus_config.glitch_ignore_cnt            = 7;    /* 对sda和scl的信号滤波，单位为时钟周期，默认7 */
    i2c_bus_config.flags.enable_internal_pullup = true; /* 启动时，启动I2C总线时，启动内部上拉 */
    i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
}

void bsp_sound_i2s_init(void)
{
    // i2s的通道配置
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    i2s_std_config_t  std_cfg  = {
          .clk_cfg  = I2S_STD_CLK_DEFAULT_CONFIG(16000),                             // 时钟配置: 参数是音频的采样率 16KHz
          .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_MONO),   // 16位的采样深度 单声道
          .gpio_cfg = {
              .mclk = I2S_MCK_PIN,
              .bclk = I2S_BCK_PIN,
              .ws   = I2S_DATA_WS_PIN,
              .dout = I2S_DATA_OUT_PIN,
              .din  = I2S_DATA_IN_PIN,
        },
    };
    // 创建输入和输出通道
    i2s_new_channel(&chan_cfg, &speakerHandle, &micHandle);

    // 初始化输出和输入通道
    i2s_channel_init_std_mode(speakerHandle, &std_cfg);
    i2s_channel_init_std_mode(micHandle, &std_cfg);

    // 使能通道
    i2s_channel_enable(speakerHandle);
    i2s_channel_enable(micHandle);
}

void bsp_sound_es8311_init(void)
{
    // i2s的配置
    audio_codec_i2s_cfg_t i2s_cfg = {
        .rx_handle = micHandle,
        .tx_handle = speakerHandle,
    };
    // 数据接口
    const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);

    // i2c的配置
    audio_codec_i2c_cfg_t i2c_cfg = {
        .port       = SOUND_PORT,
        .addr       = ES8311_CODEC_DEFAULT_ADDR,
        .bus_handle = i2c_bus_handle};
    // 控制接口
    const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);

    // gpio接口
    const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();

    // es8311编解码器配置
    es8311_codec_cfg_t es8311_cfg = {
        .codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,   // 支持播放和录音
        .ctrl_if    = out_ctrl_if,
        .gpio_if    = gpio_if,
        .pa_pin     = PA_GPIO,
        .use_mclk   = true,   // 使用mclk
    };

    // es8311编解码器接口
    const audio_codec_if_t *out_codec_if = es8311_codec_new(&es8311_cfg);

    // 编码器设备配置
    esp_codec_dev_cfg_t dev_cfg = {
        .codec_if = out_codec_if,               // codec interface from es8311_codec_new
        .data_if  = data_if,                    // data interface from audio_codec_new_i2s_data
        .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT   // codec support both playback and record
    };

    codec_dev = esp_codec_dev_new(&dev_cfg);

    // 设置麦克风增益
    esp_codec_dev_set_in_gain(codec_dev, 20.0);
    // 设置音量
    esp_codec_dev_set_out_vol(codec_dev, 60.0);
}

void bsp_sound_init(void)
{
    // 1. i2c的初始化
    bsp_sound_i2c_init();

    // 2. i2s的初始化
    bsp_sound_i2s_init();

    // 3. es8311芯片的初始化
    bsp_sound_es8311_init();
}

/**
 * @brief 打开音频设备
 */
void bsp_sound_open(void)
{
    // 采样信息
    esp_codec_dev_sample_info_t fs = {
        .sample_rate     = 16000,   // 采样率
        .channel         = 1,       // 通道数
        .bits_per_sample = 16,      // 采样位数(采样深度)
    };

    if(codec_dev)
    {
        // 打开设备
        esp_codec_dev_open(codec_dev, &fs);
    }
}

/**
 * @brief 关闭音频设备
 *
 */
void bsp_sound_close(void)
{
    if(codec_dev)
    {
        esp_codec_dev_close(codec_dev);
    }
}

/**
 * @brief 播放
 *
 * @param data
 * @param size
 */
int bsp_sound_write(uint8_t *data, int size)
{
    if(codec_dev && data && size > 0)
    {

        return esp_codec_dev_write(codec_dev, (void *)data, size);
    }

    return ESP_CODEC_DEV_WRITE_FAIL;
}

/**
 * @brief 读取麦克风的数据 录音
 *
 * @param data 存放数据的缓存
 * @param size 读取的数据的长度
 */
int bsp_sound_read(uint8_t data[], int size)
{
    if(codec_dev && data && size > 0)
    {

        // 阻塞式读取
        return esp_codec_dev_read(codec_dev, data, size);
    }

    return ESP_CODEC_DEV_READ_FAIL;
}

int  s_vol = 60;
void setVolume(int volume)
{
    if(codec_dev)
    {
        s_vol = volume;
        esp_codec_dev_set_out_vol(codec_dev, volume);
    }
}

void setMute(bool mute)
{
    if(codec_dev && mute)
    {
        esp_codec_dev_set_out_vol(codec_dev, 0);
    }
    else if(codec_dev && mute == false)
    {
        esp_codec_dev_set_out_vol(codec_dev, s_vol);
    }
}
